#! /usr/bin/python3

from PIL import Image
import os
import glob
import argparse


def rgb888_to_rgb565(r, g, b):
    r5 = min(round(r * 31 / 255), 31)
    g6 = min(round(g * 63 / 255), 63)
    b5 = min(round(b * 31 / 255), 31)

    return (r5 << 11) | (g6 << 5) | b5


def resize_image(img, size_arg):
    """
    调整图片大小
    :param img: PIL Image对象
    :param size_arg: 大小参数，如"100x200"或"100"
    :return: 调整后的Image对象
    """
    if not size_arg:
        return img

    width, height = img.size

    if 'x' in size_arg:
        # 格式为 WxH
        try:
            new_width, new_height = map(int, size_arg.split('x'))
            return img.resize((new_width, new_height), Image.Resampling.LANCZOS)
        except ValueError:
            print(f"警告: 无效的尺寸参数 '{size_arg}'，将跳过调整大小")
            return img
    else:
        # 格式为 单个数字，调整最大边
        try:
            max_size = int(size_arg)
            ratio = max_size / max(width, height)
            new_width = int(width * ratio)
            new_height = int(height * ratio)
            return img.resize((new_width, new_height), Image.Resampling.LANCZOS)
        except ValueError:
            print(f"警告: 无效的尺寸参数 '{size_arg}'，将跳过调整大小")
            return img


def image_to_rgb565_c_array(image_path, output_file, array_name, resize=None):
    """
    将图片转换为RGB565格式的C数组

    参数:
        image_path: 输入图片路径
        output_file: 输出的.c文件路径
        array_name: C数组的名称
        resize: 调整图片大小的参数
    """
    try:
        # 打开图片并转换为RGB模式
        img = Image.open(image_path).convert('RGB')

        # 调整图片大小
        if resize:
            img = resize_image(img, resize)

        width, height = img.size

        # 获取像素数据
        pixels = img.load()

        # 创建输出文件
        with open(output_file, 'w') as f:
            # 写入文件头信息
            f.write(f"/* Auto-generated from {os.path.basename(image_path)} */\n")
            f.write(f"/* Image size: {width}x{height} */\n\n")
            f.write("{\n")

            # 计数器，用于控制每行输出的元素数量
            counter = 0
            total_pixels = width * height

            # 遍历所有像素
            for y in range(height):
                for x in range(width):
                    r, g, b = pixels[x, y]
                    rgb565 = rgb888_to_rgb565(r, g, b)

                    # 每行开头添加缩进
                    if counter % 16 == 0:
                        f.write("    ")

                    f.write(f"0x{rgb565:04X}")

                    # 如果不是最后一个元素，添加逗号
                    if counter != total_pixels - 1:
                        f.write(", ")

                    # 每16个元素换行
                    if counter % 16 == 15:
                        f.write("\n")

                    counter += 1

            # 如果最后一行不足16个且未换行，补一个换行
            if counter % 16 != 0:
                f.write("\n")

            f.write("}\n")

        print(f"转换成功: {os.path.basename(image_path)} -> {output_file}")
        print(f"图像尺寸: {width}x{height}")
        print(f"数组长度: {height * width}")
        print(f"数组名称: {array_name}[{height * width}]\n")

    except Exception as e:
        print(f"处理 {image_path} 时出错: {e}")


def process_images(input_files, resize=None):
    """处理指定的图像文件"""
    if not input_files:
        print("没有指定输入文件")
        return

    print(f"开始处理 {len(input_files)} 个图像文件...\n")

    for image_path in input_files:
        # 检查文件是否存在
        if not os.path.exists(image_path):
            print(f"警告: 文件 '{image_path}' 不存在，跳过")
            continue

        # 生成输出文件名（同名的.c文件）
        base_name = os.path.splitext(os.path.basename(image_path))[0]
        output_file = f"{base_name}.cdata"
        # 使用文件名作为数组名（确保是有效的C标识符）
        array_name = ''.join(c if c.isalnum() else '_' for c in base_name)

        image_to_rgb565_c_array(image_path, output_file, array_name, resize)


def main():
    parser = argparse.ArgumentParser(description='将图片转换为RGB565格式的C数组')
    parser.add_argument('-i', '--input', nargs='+', required=True,
                        help='输入图片文件路径，支持多个文件')
    parser.add_argument('-r', '--resize',
                        help='调整图片大小，格式为WxH或单个数字(如"100x200"或"100")')

    args = parser.parse_args()

    process_images(args.input, args.resize)


if __name__ == "__main__":
    main()
